<template>
  <div class="app-container">
    <div class="form-box">
      <el-form ref="form" :model="form" label-width="120px" :rules="rules">
        <el-tabs type="border-card" class="form-tabs">
          <el-tab-pane :label="$t('common.basic_info')" class="form-tabs-tab-pane">
            <!-- 角色名称 -->
            <el-row :gutter="20" type="flex" justify="center">
              <el-col :xs="24" :sm="24" :md="20" :lg="18" :xl="16">
                <el-form-item :label="$t('role.name')" prop="name">
                  <el-input
                    v-model="form.name"
                    :placeholder="$t('role.name_tips')"
                    clearable
                  />
                </el-form-item>
              </el-col>
            </el-row>

            <!-- 角色介绍 -->
            <el-row :gutter="20" type="flex" justify="center">
              <el-col :xs="24" :sm="24" :md="20" :lg="18" :xl="16">
                <el-form-item
                  :label="$t('role.description')"
                  prop="description"
                >
                  <el-input
                    v-model="form.description"
                    type="textarea"
                    :placeholder="$t('role.description_tips')"
                  />
                </el-form-item>
              </el-col>
            </el-row>

            <!-- 菜单权限 -->
            <el-row :gutter="20" type="flex" justify="center">
              <el-col :xs="24" :sm="24" :md="20" :lg="18" :xl="16">
                <el-form-item :label="$t('role.menu_ids')" prop="menu_ids" class="table-box">

                  <el-table
                    ref="menuTreeTable"
                    v-loading="roleMenuListLoading"
                    :data="roleMenuList"
                    row-key="id"
                    border
                    fit
                    highlight-current-row
                    :default-expand-all="isMenuExpand"
                    style="width: 100%"
                    :indent="12"
                    class="jsp-scroller"
                    :cell-class-name="handleMenuCellClassName"
                    :header-cell-class-name="handleMenuHeaderCellClassName"
                    @selection-change="handleMenuSelectionChange"
                    @select-all="selectMenuAll"
                    @select="handleMenuSelectCheckbox"
                  >
                    <el-table-column type="selection" align="center" fixed="left" />

                    <el-table-column
                      align="left"
                      :label="$t('common.menu')"
                      class-name="menuIcon"
                      min-width="150px"
                      fixed="left"
                      :title="$t('common.updown')"
                    >
                      <template slot="header">
                        <span :title="$t('common.updown')" style="cursor:pointer" @click="handleMenuUpDown()"><i class="el-icon-sort" /> {{ $t('common.menu') }}</span>
                      </template>
                      <template slot-scope="{ row }">
                        <span>{{ row.name }}</span>
                      </template>
                    </el-table-column>

                    <el-table-column
                      align="left"
                      :label="$t('role.priv')"
                      class-name="menuIcon"
                      min-width="240px"
                      fixed="left"
                    >
                      <template slot="header" slot-scope=" { column }">
                        <el-checkbox v-model="isTablePermissionCheckAll" :indeterminate="isTablePermissionIndeterminate" @change="handleTablePermissionCheckAllChange($event)">{{ column.label }}</el-checkbox>
                      </template>
                      <template slot-scope="{row}">
                        <el-checkbox v-if="row.role_permission_config.length>0" v-model="isRowPermissionCheckAll[row.id]" :indeterminate="isRowPermissionIndeterminate[row.id]" @change="handleRowPermissionCheckAllChange(row, $event)">{{ $t('common.checkAll') }}</el-checkbox>
                        <el-checkbox-group v-model="checkbox_permission_ids[row.id]" @change="handleCheckedRowPermissionChange(row, $event)">
                          <el-checkbox v-for="item in row.role_permission_config" :key="item.id" :label="item.id">{{ item.name }}</el-checkbox>
                        </el-checkbox-group>
                        <span v-if="row.role_permission_config.length==0">
                          -
                        </span>
                      </template>
                    </el-table-column>
                  </el-table>
                </el-form-item>
              </el-col>
            </el-row>

            <!--栏目权限-->
            <el-row :gutter="20" type="flex" justify="center">
              <el-col :xs="24" :sm="24" :md="20" :lg="18" :xl="16">
                <el-form-item :label="$t('role.category_ids')" prop="category_ids">
                  <el-alert
                    :title="$t('role.category_ids_select_tips')"
                    type="warning"
                    class="route_settings_tips"
                  />
                  <el-tree
                    ref="categoryTree"
                    :data="roleCategory"
                    :props="{ children: 'children', label: 'name' }"
                    show-checkbox
                    node-key="id"
                    :empty-text="category_empty_text"
                    :element-loading-text="$t('common.loading')"
                    :default-checked-keys="form.category_ids"
                    :default-expand-all="false"
                    @check-change="handleCategoryCheckChange"
                  >
                    <span slot-scope="{ node, data }" class="custom-tree-node">
                      <span>{{ node.label }}{{ data.model?` [${data.model.name}] `:'' }}{{ data.type==3?` [${data.type_name}] `:'' }}</span>
                    </span>
                  </el-tree>
                </el-form-item>
              </el-col>
            </el-row>

            <!-- 发布状态 -->
            <el-row :gutter="20" type="flex" justify="center">
              <el-col :xs="24" :sm="24" :md="20" :lg="18" :xl="16">
                <el-form-item
                  :label="$t('common.status')"
                  prop="status"
                >
                  <el-select
                    v-model.number="form.status"
                    :placeholder="$t('common.pleaseSelect')+$t('common.status')"
                    clearable
                  >
                    <el-option
                      v-for="item in dictionaryService.getItems('statusVar')"
                      :key="item.id"
                      :label="item.name"
                      :value="Number(item.value)"
                    />

                  </el-select>
                </el-form-item>
              </el-col>
            </el-row>
          </el-tab-pane>
        </el-tabs>

        <el-row :gutter="20" type="flex" justify="center" class="btn-row">
          <el-col :xs="24" :sm="24" :md="20" :lg="18" :xl="16">
            <el-form-item>
              <el-button
                type="primary"
                :loading="submitLoading"
                :disabled="routerParams.id>0&&!checkPermission(['admin.role.update']) || !routerParams.id&&!checkPermission(['admin.role.store'])"
                @click="onSubmit"
              >{{
                $t('common.submit')
              }}</el-button>
              <el-button @click="onCancel">{{ $t('common.cancel') }}</el-button>
            </el-form-item>
          </el-col>
        </el-row>
      </el-form>
    </div>
  </div>
</template>

<script>
import { getRoleMenuConfig } from '@/api/menu'
import { show, update, store } from '@/api/role'
import { loadingStart } from '@/utils/loading-service'
import { getCategoryTreeConfig } from '@/api/info-category'
import { treeToFlat } from '@/utils/tree'
import checkPermission from '@/utils/permission'

// export
export default {
  name: 'RoleEdit',
  components: {},
  data() {
    return {
      submitLoading: false,
      category_empty_text: this.$t('common.loading'),
      roleMenuListLoading: true,
      isMenuExpand: false,
      isMenuSelected: false,
      isRowPermissionCheckAll: [], // 权限表级全选状态列表
      isRowPermissionIndeterminate: [], // 权限行级全选不确定状态列表
      isTablePermissionCheckAll: false, // 权限表级复选框是否全选
      isTablePermissionIndeterminate: false, // 权限表级复选框不确定状态状态
      isbuildMenuCheckboxRelation: true, // 菜单行级复选框选择时是否关联上下级
      form: {
        id: 0,
        name: '',
        menu_permission_ids: [], // 栏目权限id集：[<menu_id>:[<permission_id1>,]]
        category_ids: [],
        description: '',
        status: 1
      },
      checkbox_permission_ids: [], // 权限id选中集：[<menu_id>:[<permission_id1>,]]
      // 表单输入校验 ，通过prop="name"属性进行控制
      rules: {
        name: [
          { required: true, message: this.$t('role.name_tips'), trigger: 'blur' },
          { min: 2, max: 30, message: this.$t('role.name_length_tips'), trigger: 'blur' }
        ]
      },
      // 路由参数
      routerParams: {},
      back_route_name: 'RoleIndex',
      // 菜单
      roleMenuList: [],
      menuMultipleSelection: [],
      roleMenuListToFlat: [],
      // 完整权限id集合
      tableAllPermissionIds: [],
      // 栏目数据
      roleCategory: []

    }
  },
  watch: {
  },
  created() {
    this.routerParams = this.$route.params
  },
  mounted() {
    this.getDetail()
  },
  methods: {
    checkPermission,
    async getDetail() {
      const loading = loadingStart()
      const { id } = this.routerParams
      if (id > 0) {
        await show(id).then((response) => {
          const data = response.data
          for (const key in data) {
            if (key in this.form) {
              this.form[key] = data[key]
            }
          }
        }).catch(() => {
          this.closeBack(this.back_route_name)
        })
      }
      // 菜单权限
      getRoleMenuConfig().then((response) => {
        const { items } = response.data
        this.roleMenuList = items
        this.roleMenuListToFlat = treeToFlat(items)
        let all_permission_total = 0
        let all_selected_permission_total = 0
        this.roleMenuListToFlat.forEach((row, index) => {
          // 权限：行级权限数据回显、全选
          const selected_menu_permission_ids = this.form.menu_permission_ids[row.id] ?? []
          const permission_total = Object.keys(row.role_permission_config).length
          const selected_permission_total = Object.keys(selected_menu_permission_ids).length
          this.checkbox_permission_ids[row.id] = selected_menu_permission_ids
          this.isRowPermissionCheckAll[row.id] = permission_total === selected_permission_total
          this.isRowPermissionIndeterminate[row.id] = selected_permission_total > 0 && selected_permission_total < permission_total
          all_permission_total += permission_total
          all_selected_permission_total += selected_permission_total
          // 菜单：复选框回显
          if (this.form.menu_permission_ids[row.id] !== undefined) {
            this.$nextTick(() => {
              row['isSelected'] = true
              this.$refs.menuTreeTable.toggleRowSelection(row, true)
            })
          }
        })
        // 权限：表级全选回显
        this.isTablePermissionCheckAll = all_permission_total === all_selected_permission_total
        this.isTablePermissionIndeterminate = all_selected_permission_total > 0 && all_selected_permission_total < all_permission_total
        this.roleMenuListLoading = false
      }).catch(() => {})

      // 栏目权限
      getCategoryTreeConfig().then((reponse) => {
        this.roleCategory = reponse.data.items
        if (this.roleCategory.length === 0) this.category_empty_text = this.$t('common.empty')
        this.$nextTick(() => {
          this.$refs.categoryTree.setCheckedKeys(this.form.category_ids)
        })
      }).catch(() => {})

      loading.close()
    },
    onSubmit() {
      this.$refs['form'].validate(async(valid) => {
        this.form.menu_permission_ids = []
        this.menuMultipleSelection.forEach((item, index) => {
          this.form.menu_permission_ids[index] = { menu_id: item.id, permission_ids: this.checkbox_permission_ids[item.id] }
        })
        if (valid) {
          this.submitLoading = true
          let response
          if (this.routerParams.id) {
            response = await update(this.routerParams.id, this.form).catch(() => {})
          } else {
            response = await store(this.form).catch(() => {})
          }
          if (response instanceof Object) {
            this.$message.success(response.message)
            this.closeBack(this.back_route_name)
          }
          this.submitLoading = false
        } else {
          this.$message.error(this.$t('common.pleaseFillRequired'))
          return false
        }
      })
    },
    onCancel() {
      this.closeBack(this.back_route_name)
    },
    // 菜单：收起/展开实际执行
    menuDownUpData(data, isExpand) {
      data.forEach((i) => {
        if (i.children) {
          this.$refs.menuTreeTable.toggleRowExpansion(i, isExpand)
          this.menuDownUpData(i.children, isExpand)
        }
      })
    },
    // 菜单：收起/展开事件
    handleMenuUpDown() {
      this.isMenuExpand = !this.isMenuExpand
      this.menuDownUpData(this.roleMenuList, this.isMenuExpand)
    },
    // 菜单：选择改变事件
    handleMenuSelectionChange(val) {
      this.menuMultipleSelection = val
    },
    // 菜单：获取所有子选项复选框总数量、已选中数量
    getAllMenuChildrenCheckboxTotal(children_data) {
      const result = { total: 0, selected: 0 }
      if (!children_data) return result
      children_data.forEach(item => {
        result.total++
        result.selected += item.isSelected ? 1 : 0
        if (item.children) {
          const getC = this.getAllMenuChildrenCheckboxTotal(item.children)
          result.total += getC.total
          result.selected += getC.selected
        }
      })
      return result
    },
    // 菜单：表级全选/取消复选框
    selectMenuAll(selection) {
      this.roleMenuList.forEach((item) => {
        this.executeMenuSelectRow(selection, item)
      })
    },
    // 菜单：执行行级选择/取消
    executeMenuSelectRow(selection, row) {
      // 选中状态判断
      const rowIsSelected = selection.some(item => { return row.id === item.id })
      row.isSelected = rowIsSelected
      const that = this

      // 设置所有子项选中/取消
      function setChildrensCheckboxSelected(children_data) {
        children_data.forEach(item => {
          that.$nextTick(() => {
            item.isSelected = rowIsSelected
            that.$refs.menuTreeTable.toggleRowSelection(item, rowIsSelected)
            if (item.children) {
              setChildrensCheckboxSelected(item.children, rowIsSelected)
            }
          })
        })
      }

      // 设置所有父级选中状态
      function setAllParentSelectedStatus(data) {
        if (data.length === 0) return
        for (let i = 0; i < data.length; i++) {
          if (data[i].id === row.id) {
            return []
          } else {
            if (data[i].children) {
              const res = setAllParentSelectedStatus(data[i].children)
              if (res !== undefined) {
                that.$nextTick(() => {
                  if (rowIsSelected) { // 选中情况
                    data[i].isSelected = true
                  } else { // 取消选中情况
                    const getCT = that.getAllMenuChildrenCheckboxTotal(data[i].children)
                    const isSelected = getCT.selected > 0
                    data[i].isSelected = isSelected
                  }
                  that.$refs.menuTreeTable.toggleRowSelection(data[i], data[i].isSelected)
                })
                return []
              }
            }
          }
        }
      }

      // 子级选中状态处理
      if (row.children) {
        // 设置子选项选中状态
        setChildrensCheckboxSelected(row.children)
      }
      // 设置父选项选中状态
      setAllParentSelectedStatus(this.roleMenuList)
    },
    // 菜单：行级复选框选中/取消事件
    handleMenuSelectCheckbox(selection, row) {
      this.isbuildMenuCheckboxRelation && this.executeMenuSelectRow(selection, row)
    },
    // 菜单：设置列样式名
    handleMenuCellClassName(cell) {
      if (this.isbuildMenuCheckboxRelation && cell.columnIndex === 0) {
        const getCT = this.getAllMenuChildrenCheckboxTotal(cell.row.children)
        if (getCT.selected > 0 && getCT.selected < getCT.total) {
          return 'jsp-is-indeterminate'
        }
        return ''
      }
    },
    // 菜单：设置头部列样式
    handleMenuHeaderCellClassName(cell) {
      if (this.isbuildMenuCheckboxRelation && cell.columnIndex === 0) {
        let total = 0
        let selected_total = 0
        this.roleMenuList.forEach((item) => {
          if (item.children) {
            const getCT = this.getAllMenuChildrenCheckboxTotal(item.children)
            total += getCT.total
            selected_total += getCT.selected
          }
        })
        if (selected_total > 0 && selected_total < total) {
          return 'jsp-is-indeterminate'
        }
        return ''
      }
    },
    // 权限：设置表级全选按钮全选或取消
    setTablePermissionCheckboxSelected() {
      const allLength = Object.keys(this.isRowPermissionCheckAll).length
      const isAllSelectedLength = this.isRowPermissionCheckAll.filter((item, index) => {
        return item === true
      }).length
      this.isTablePermissionCheckAll = allLength === isAllSelectedLength
      this.isTablePermissionIndeterminate = isAllSelectedLength > 0 && isAllSelectedLength < allLength
    },
    // 权限：行级全选/取消事件
    handleRowPermissionCheckAllChange(menu, e) {
      const allPermissionIds = menu.role_permission_config.map((item) => {
        return item.id
      })
      this.checkbox_permission_ids[menu.id] = e ? allPermissionIds : []
      this.isRowPermissionIndeterminate[menu.id] = false
      this.setTablePermissionCheckboxSelected()
    },
    // 权限：重新渲染
    refreshPermissionIds() {
      this.checkbox_permission_ids.forEach((item, index) => {
        this.$set(this.checkbox_permission_ids, index, item)
      })
    },
    // 权限：行级复选框选择事件
    handleCheckedRowPermissionChange(menu, e) {
      const checkedCount = e.length
      const allPermissionIdsLength = menu.role_permission_config.map((item) => {
        return item.id
      }).length
      this.isRowPermissionCheckAll[menu.id] = checkedCount === allPermissionIdsLength
      this.isRowPermissionIndeterminate[menu.id] = checkedCount > 0 && checkedCount < allPermissionIdsLength
      this.setTablePermissionCheckboxSelected()
      this.refreshPermissionIds()
    },
    // 权限：表级全选/取消
    handleTablePermissionCheckAllChange(e) {
      this.isRowPermissionCheckAll.forEach((item, id) => {
        this.isRowPermissionCheckAll[id] = e
      })
      this.isRowPermissionIndeterminate.forEach((item, id) => {
        this.isRowPermissionIndeterminate[id] = false
      })
      this.roleMenuListToFlat.forEach((row, index) => {
        const getRowPermissionIds = row.role_permission_config.map((item) => {
          return item.id
        })
        this.checkbox_permission_ids[row.id] = e ? getRowPermissionIds : []
      })
      this.setTablePermissionCheckboxSelected()
      this.refreshPermissionIds()
    },
    // 栏目：权限选择
    handleCategoryCheckChange(data, checked, indeterminate) {
      const resultChecked = this.$refs.categoryTree.getCheckedNodes()
      this.form.category_ids = resultChecked.map((e) => {
        return e.id
      })
    }
  }
}
</script>

<style scoped lang="scss">
</style>
